package com.javandad.app.server.servlet;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.SortedSet;

import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.google.appengine.repackaged.com.google.common.collect.SortedArraySet;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.javandad.app.client.chat.ChatService;
import com.javandad.app.server.UserManager;
import com.javandad.app.server.db.PMFSingleton;
import com.javandad.app.shared.entity.ChatMessage;
import com.javandad.app.shared.entity.User;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class ChatServiceImpl extends RemoteServiceServlet implements ChatService {

	@Override
	public ChatMessage send(String receiverId, String text) {
		PersistenceManager pm = PMFSingleton.getPM();
		User sender = UserManager.getCurrentUser(pm);
		if (sender == null)
			return null;
		User receiver = pm.getObjectById(User.class, receiverId);
		if (receiver == null)
			return null;
		ChatMessage m = new ChatMessage(sender, receiver, text, new Date());
		pm.makePersistent(m);
		pm.close();
		return m;
	}

	@Override
	public List<User> whosOnline() {
		PersistenceManager pm = PMFSingleton.getPM();
		try {
			//System.out.println("whosOnline");
			List<User> online = getPresentUsers(pm);
			User user = UserManager.getCurrentUser(pm);
			if (user != null) {
				user.setLastChatPoll(new Date());
				pm.makePersistent(user);
				//online.remove(user);
			}
			//online.add(pm.getObjectById(User.class, "12501881701511352185"));
			pm.close();
			return online;
		} catch (JDOException e) {
			//System.out.println(e.getMessage());
			return new ArrayList<User>();
		}
	}

	/** User is considered present if last chat poll is <= PresenceTime ms ago */
	public static final int PresenceTime = 6*1000;
	
	public static List<User> getPresentUsers(PersistenceManager pm) {
		Date presentDate = new Date();
		presentDate.setTime(presentDate.getTime() - PresenceTime);
		SortedSet<User> sorter = new SortedArraySet<User>(new Comparator<User>() {
			@Override
			public int compare(User o1, User o2) {
				return o1.toString().compareTo(o2.toString());
			}
		});
		Query q = pm.newQuery(User.class);
		q.setFilter("lastChatPoll >= dateParam");
		q.declareImports("import java.util.Date");
		q.declareParameters("Date dateParam");
		@SuppressWarnings("unchecked")
		List<User> result = (List<User>) q.execute(presentDate);
		sorter.addAll(result);
		List<User> presentUsers = new ArrayList<User>();
		presentUsers.addAll(sorter);
		// System.out.println("present: "+presentUsers);
		return presentUsers;
	}

	@Override
	public List<ChatMessage> poll() {
		PersistenceManager pm = PMFSingleton.getPM();
		try {
			//System.out.println("poll");
			User user = UserManager.getCurrentUser(pm);
			if (user == null)
				return null;
			Date now = new Date();
			List<ChatMessage> messages = getNewMessages(user, pm);
			user.setLastChatPoll(now);
			pm.makePersistent(user);
			pm.close();
			return messages;
		} catch (JDOException e) {
			//System.out.println(e.getMessage());
			return new ArrayList<ChatMessage>();
		}
	}

	public static List<ChatMessage> getNewMessages(User receiver, PersistenceManager pm) {
		Query q = pm.newQuery(ChatMessage.class);
		q.setFilter("receiverId == receiverParam && when >= dateParam");
		q.declareImports("import java.util.Date");
		q.declareParameters("String receiverParam, Date dateParam");
		@SuppressWarnings("unchecked")
		List<ChatMessage> result = (List<ChatMessage>) q.execute(receiver.getUserId(), receiver.getLastChatPoll());
		List<ChatMessage> messages = new ArrayList<ChatMessage>();
		for (ChatMessage m : result) {
			if (m.sender == null)
				m.sender = pm.getObjectById(User.class, m.getSenderId());
			messages.add(m);
		}
		return messages;
	}
}
